package cn.pink.gamesrv.human;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.pink.common.constant.DBConst;
import cn.pink.common.entity.game.info.EntityHumanInfo;
import cn.pink.common.proto.Msg;
import cn.pink.common.proto.MsgIds;
import cn.pink.common.support.tools.rpc.RpcTool;
import cn.pink.core.CallPoint;
import cn.pink.core.Chunk;
import cn.pink.core.Port;
import cn.pink.core.entity.EntityProxy;
import cn.pink.gamesrv.human.module.IMod;
import cn.pink.gamesrv.human.module.group.ModGroup;
import cn.pink.gamesrv.human.module.item.ModItem;
import cn.pink.gatesrv.RPCProxy;
import com.google.protobuf.Message;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author: pink
 * @Date: 2022/7/7 11:13
 */
public class HumanObject {
    /** 玩家id */
    @Getter
    private String id;

    /** sessionPoint */
    @Getter
    @Setter
    private CallPoint sessionPoint;

    /** dbPoint */
    @Getter
    @Setter
    private CallPoint dbPoint;

    @Getter
    private HumanObjectService humanObjSrv;

    /** 正在登陆中 */
    @Getter
    private boolean logging = true;

    /** 登录的token */
    private String token = "";

    /** 开放平台id */
    private String userIdentity = "";

    /** 角色所有模块 */
    private List<IMod> mods = new ArrayList<>();

    @Getter
    private ModItem modItem;

    @Getter
    private ModGroup modGroup;

    private EntityHumanInfo humanInfoDB;

    public HumanObject(String id, CallPoint sessionPoint, String userIdentity, String token, HumanObjectService humanObjSrv) {
        this.id = id;
        this.sessionPoint = sessionPoint;
        this.token = token;
        this.userIdentity = userIdentity;
        this.humanObjSrv = humanObjSrv;
    }

    public Future<Void> login() {
        createMod();
        return loadData();
    }

    private void createMod() {
        modItem = new ModItem(this);
        mods.add(modItem);

        modGroup = new ModGroup(this);
        mods.add(modGroup);
    }

    private Future<Void> loadData() {
        Promise<Void> promise = Promise.promise();

        RpcTool.getInstance().findHuman(id).onSuccess(data -> {
            load(data);
            promise.complete();
        });

        return promise.future();
    }

    private void load(String db) {
        if(StrUtil.isEmptyIfStr(db)) {
            //创建角色
            createHuman();
        }
        else {
            humanInfoDB = (EntityHumanInfo) createAndInitEntityProxy(EntityHumanInfo.class, new JSONObject(db).getJSONObject(DBConst.DB_KEY_HUMAN_INFO)).getEntity();
        }

        HumanManager.load(this, db);
    }

    /**
     * 创建角色
     */
    public void createHuman() {
        humanInfoDB = (EntityHumanInfo) createEntityProxy(EntityHumanInfo.class).getEntity();

        humanInfoDB.setAccount(Port.applyId());
//        humanInfoDB.setAccount(UniqueID.nextID(0));

        humanInfoDB.setName("test");
        humanInfoDB.setChannelId("0");
        humanInfoDB.setDeviceId("abc");
        humanInfoDB.setLevel(1);
        humanInfoDB.setTimeLogin(Port.getTime());
        humanInfoDB.setTimeRegister(Port.getTime());
    }

    public EntityProxy createEntityProxy(Class<?> entityClass) {
        EntityProxy proxy = new EntityProxy(entityClass);
        proxy.createProxy(id);

        getHumanObjSrv().regHumanEntity(proxy);

        return proxy;
    }

    public EntityProxy createEntityProxy(Class<?> entityClass, Object mid) {
        EntityProxy proxy = new EntityProxy(entityClass);
        proxy.createProxy(id, mid);

        getHumanObjSrv().regHumanEntity(proxy);

        return proxy;
    }

    public EntityProxy createAndInitEntityProxy(Class<?> entityClass, Map<String, Object> data) {
        EntityProxy proxy = new EntityProxy(entityClass);

        proxy.createProxy(id);
        proxy.initEntity(data);

        getHumanObjSrv().regHumanEntity(proxy);

        return proxy;
    }

    public EntityProxy createAndInitEntityProxy(Class<?> entityClass, Object mid, Map<String, Object> data) {
        EntityProxy proxy = new EntityProxy(entityClass);

        proxy.createProxy(id, mid);
        proxy.initEntity(data);

        getHumanObjSrv().regHumanEntity(proxy);

        return proxy;
    }

    /**
     * 各个模块load数据之后 回调
     */
    public void afterReadData() {
        mods.forEach(IMod::afterReadData);
    }

    /**
     * 角色登录完成回调
     */
    public void loginFinish() {
        logging = false;

        mods.forEach(IMod::loginFinish);

        pushData();
    }

    /**
     *  1次将所有角色数据推给客户端
     */
    public void pushData() {
        Msg.SCSPO.Builder msg = Msg.SCSPO.newBuilder();
        msg.setItem((Msg.DItemSPO) getModItem().build2ClientData());

        sendMsg(msg);
    }

    /**
     * 发送消息至玩家
     */
    public void sendMsg(Message.Builder builder) {
        getHumanObjSrv().pulseEntityModifyUpdate();

        if (builder != null) {
            sendMsg(builder.build());
        }
    }

    /**
     * 发送消息至玩家
     */
    public void sendMsg(Message msg) {
        if (msg != null) {
            int msgId = MsgIds.getIdByClass(msg.getClass());
            sendMsg(msgId, new Chunk(msg));
        }
    }

    /**
     * 发送消息至玩家
     */
    public void sendMsg(int msgId, Chunk msgChunk) {
        RPCProxy.SessionServiceProxy proxy = RPCProxy.SessionServiceProxy.newInstance(sessionPoint);
        proxy.sendMsg(msgId, msgChunk);
    }
}
